﻿// step 1: Determine Dominant Characteristic - a combination of hair colour, eye colour and skin tone 
// once skin tone, hair and eye colour are known, retrieve result from relevant 2D array at index position of hair and eye colour
// relevant array to search is determined by skin tone selection: Light, Medium or Dark
// arrays stored here in Web Service 

// step 2: Determine Secondary Characteristic - Based on Dominant Characteristic phone app asks user if Light versus Deep OR Warm versus Cool colours complement their look more
// this is done in the phone client

// step 3: Determine ColourTypeName which is a result of Dominant Characteristic + Secondary Characteristic
// retrieve result from 2D array at index position of Dominant and Secondary Characteristic
// array stored here in Web Service

using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.Data.Objects;
using System.Data;
using System.Data.Entity;
using System.Data.SqlClient;
using System.Web.Services.Protocols;
using System.Web;

namespace ColourAppWebService
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "ColourTypeService" in code, svc and config file together.

    public class ColourTypeService : IColourTypeService
    {
        // read write property for Dominant and Secondary Characteristic
        public DominantCharacteristic DominantCharacteristic { get; set; }
        public SecondaryCharacteristic SecondaryCharacteristic { get; set; }

        private const int NoDominantCharacteristics = 6;
        private const int NoSecondaryCharacteristics = 4;

        // read write property for colour type
        public ColourTypeName ColourType { get; set; }

        // 2D array of enum DominantCharacteristic type based on light skin tone selection. Rows are hair colours and columns are eye colours
        private DominantCharacteristic[,] colourOptionsLightSkin;

        // 2D array of enum DominantCharacteristic type based on medium skin tone selection. Rows are hair colours and columns are eye colours       
        private DominantCharacteristic[,] colourOptionsMedSkin;

        // 2D array of enum DominantCharacteristic type based on dark skin tone selection. Rows are hair colours and columns are eye colours        
        private DominantCharacteristic[,] colourOptionsDarkSkin;

        // 2D array of enum ColourTypeName type to hold possible colour type results. Rows are DominantCharacteristics and columns are SecondaryCharacteristics 
        private ColourTypeName[,] colourTypeOptions;

        // constructor
        public ColourTypeService()
        {
            // call methods from ColourOptions class to initialize the three 2D arrays for light, medium and dark skin tone
            colourOptionsLightSkin = ColourOptions.InitializeLightSkin();

            colourOptionsMedSkin = ColourOptions.InitializeMedSkin();

            colourOptionsDarkSkin = ColourOptions.InitializeDarkSkin();

            // 2D array of enum ColourTypeName type to hold possible colour type results based on combinations of DominantCharacteristic + SecondaryCharacteristic. 
            // Rows are DominantCharacteristics and columns are SecondaryCharacteristics 
            colourTypeOptions = new ColourTypeName[NoDominantCharacteristics, NoSecondaryCharacteristics];

            // DominantCharacteristic + SecondaryCharacteristic = ColourType
            // Users Dominant Characteristic has been determined from above steps and is stored in isolated storage on phone
            // Based on this Dominant Characteristic the app on the phone will ask the user one of 2 possible questions:
            // 1. if warm or cool colours OR 
            // 2. if light or deep colours enhance their colouring more
            // The answer to the question is the users Secondary Characteristic

            // result for row 0 (Deep) + column 0 (Cool) and so on
            colourTypeOptions[0, 0] = ColourTypeName.DeepWinter;
            colourTypeOptions[0, 1] = ColourTypeName.DeepAutumn;
            //colourTypeOptions[0, 2] = N/A
            //colourTypeOptions[0, 3] = N/A

            // result for row 1 (Light) + column 0 (Cool) and so on
            colourTypeOptions[1, 0] = ColourTypeName.LightSummer;
            colourTypeOptions[1, 1] = ColourTypeName.LightSpring;
            //colourTypeOptions[1, 2] = N/A
            //colourTypeOptions[1, 3] = N/A

            // result for row 2 (Bright) + column 0 (Cool) and so on
            colourTypeOptions[2, 0] = ColourTypeName.BrightWinter;
            colourTypeOptions[2, 1] = ColourTypeName.BrightSpring;
            //colourTypeOptions[2, 2] = N/A
            //colourTypeOptions[2, 3] = N/A

            // result for row 3 (Soft) + column 0 (Cool) and so on
            colourTypeOptions[3, 0] = ColourTypeName.SoftSummer;
            colourTypeOptions[3, 1] = ColourTypeName.SoftAutumn;
            //colourTypeOptions[3, 2] = N/A
            //colourTypeOptions[3, 3] = N/A

            // result for row 4 (Warm) + column 0 (Cool) and so on
            colourTypeOptions[4, 0] = ColourTypeName.WarmSpring;
            colourTypeOptions[4, 1] = ColourTypeName.WarmAutumn;
            colourTypeOptions[4, 2] = ColourTypeName.WarmAutumn;
            colourTypeOptions[4, 3] = ColourTypeName.WarmSpring;

            // result for row 5 (Cool) + column 0 (Cool) and so on
            colourTypeOptions[5, 0] = ColourTypeName.CoolWinter;
            colourTypeOptions[5, 1] = ColourTypeName.CoolSummer;
            colourTypeOptions[5, 2] = ColourTypeName.CoolWinter;
            colourTypeOptions[5, 3] = ColourTypeName.CoolSummer;
        }

        // method to determine Dominant Characteristic 
        // There are 3 skin tone options so need to indicate in method which array to read 
        // Pass in skin tone selection as parameter then use if else statement to determine which array to read result from 
        public DominantCharacteristic DetermineDominantCharacteristic(int hairIndex, int eyeIndex, int skinIndex)
        {
            if (skinIndex == 0)
            {
                DominantCharacteristic = colourOptionsLightSkin[hairIndex, eyeIndex];
                return DominantCharacteristic;
            }
            else if (skinIndex == 1)
            {
                DominantCharacteristic = colourOptionsMedSkin[hairIndex, eyeIndex];
                return DominantCharacteristic;
            }
            else
            {
                DominantCharacteristic = colourOptionsDarkSkin[hairIndex, eyeIndex];
                return DominantCharacteristic;
            }
        }

        // method to determine the colour type based on the Dominant Characteristic plus the Secondary Characteristic
        public ColourTypeName DiscoverColourType(DominantCharacteristic dominantCharacteristic, SecondaryCharacteristic secondaryCharacteristic)
        {
            ColourType = colourTypeOptions[(int)dominantCharacteristic, (int)secondaryCharacteristic];
            return ColourType;
        }

        // method to get description attribute of ColourTypeName enums declared in service interface
        // need this so can pass as string value in LINQ query to database
        public static string GetEnumDescription(Enum value)
        {
            System.Reflection.FieldInfo field = value.GetType().GetField(value.ToString());

            System.ComponentModel.DescriptionAttribute[] attributes =
                (System.ComponentModel.DescriptionAttribute[])field.GetCustomAttributes(typeof(System.ComponentModel.DescriptionAttribute), false);

            if (attributes != null && attributes.Length > 0)
                return attributes[0].Description;
            else
                return value.ToString();
        }

        // method to return a colour type object for a specified colour type name. Object returned contains id, name and description. 
        // Description will be displayed on phone client and id used for operation to get fashion trends description 
        public ColourType DisplayColourTypeDescription(ColourTypeName colourType)
        {
            // db refers to the connection to the SQL Azure database and FashionColourAdvisor is the name of database 
            FashionColourAdvisorContext db = new FashionColourAdvisorContext();

            String name = GetEnumDescription(colourType);

            // use this string value rather than colourType enum in LINQ query because colourType_name is stored as a varchar in database table 
            var colourTypeDescriptionQuery = db.ColourTypes
                                            .Where(t => t.colourType_name == name); // t is the colour Type object

            // result of LINQ query is a list of colour type objects and there should be only one colour type object returned
            ColourType result = colourTypeDescriptionQuery.ToList().ElementAt(0);
            return result;         
        }

        // method to get fashion trends description for a specified colour type 
        public String DisplayFashionTrendsDescription(String colourType_id, String season_name, Int16 season_year)
        {
            // db refers to the connection to the SQL Azure database and FashionColourAdvisor is the name of database 
            FashionColourAdvisorContext db = new FashionColourAdvisorContext();

            // values passed in are used in LINQ query to retrieve the description from the fashionAdvices table 
            var fashionTrendsDescriptionQuery = db.FashionAdvices
                                            .Where(advice => advice.colourType_id == colourType_id && advice.season_name == season_name && advice.season_year == season_year);

            // result of LINQ query is a list of type FashionAdvice objects 
            List<FashionAdvice> result = fashionTrendsDescriptionQuery.ToList();

            //the fashionAdvice_description is stored as a varchar in the database table  
            String fashionTrendsDescription = null;

            // there should be only one object returned in the list which is at position 0
            FashionAdvice adviceResult = result.ElementAt(0);

            // assign the fashion advice description property of this object to fashionTrendsDescription because only want this property of the object
            fashionTrendsDescription = adviceResult.fashionAdvice_description;

            return fashionTrendsDescription;
        }
    }
}
